package cn.jasonone.jfx.factory;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ClassUtil;
import javafx.beans.property.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xujie
 * @version 1.0
 * @date 2021/12/23 14:30
 */
@Component("propertyFactoryManager")
public class JfxPropertyFactory implements PropertyFactory, InitializingBean {
    @Resource
    private ApplicationContext applicationContext;
    private Map<Class<?>, PropertyFactory> propertyFactories = new HashMap<>();

    @Override
    public void afterPropertiesSet() throws Exception {
        Map<String, PropertyFactory> propertyFactoryMap = applicationContext.getBeansOfType(PropertyFactory.class);
        Collection<PropertyFactory> values = propertyFactoryMap.values();
        for (PropertyFactory propertyFactory : values) {
            if (propertyFactory == this) {
                continue;
            }
            Class<?> propertyFactoryType = ClassUtil.getTypeArgument(propertyFactory.getClass());
            propertyFactories.put(propertyFactoryType, propertyFactory);
        }
    }

    private <P extends Property> P getDefaultInstance(Class<?> type) {
        if (IntegerProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleIntegerProperty();
        } else if (FloatProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleFloatProperty();
        } else if (DoubleProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleDoubleProperty();
        } else if (StringProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleStringProperty();
        } else if (BooleanProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleBooleanProperty();
        } else if (LongProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleLongProperty();
        } else if (ListProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleListProperty();
        } else if (MapProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleMapProperty();
        } else if (SetProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleSetProperty();
        } else if (ObjectProperty.class.isAssignableFrom(type)) {
            return (P) new SimpleObjectProperty();
        }
        return null;
    }

    @Override
    public <P extends Property> P getInstance(Class<?> type) {
        if (propertyFactories.containsKey(type)) {
            PropertyFactory propertyFactory = propertyFactories.get(type);
            Assert.notNull(propertyFactory, "属性工厂[{}]为空", type);
            return propertyFactory.getInstance(type);
        }
        return this.getDefaultInstance(type);
    }
}
